package com.incom.log.server.run;

import com.incom.log.server.conf.MqConfig;
import com.incom.log.server.conf.ServiceConfig;
import com.incom.log.server.conf.redis.RedisConfig;
import com.incom.log.server.mq.LogService;
import com.incom.log.server.mq.impl.RedisLogService;
import com.incom.log.server.thread.PringThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class PrintLog {

    private List<LogService> logServices = new ArrayList<>();

    private static Logger log = LoggerFactory.getLogger(PrintLog.class);

    private ServiceConfig config;

    private void init() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Properties p = config.getProperties();
        String property = p.getProperty("log-service");
        for (Map.Entry<Object, Object> entry : p.entrySet()) {
            if(entry.getKey().toString().startsWith("log-service")) {
                String serviceName = entry.getKey().toString().substring(entry.getKey().toString().indexOf(".") + 1);
                Class<?> aClass = Class.forName(entry.getValue().toString());
                MqConfig mqConfig = getMqConfig(aClass, serviceName);
                log.info(mqConfig.toString());
                Constructor<?> constructor = aClass.getConstructor(mqConfig.getClass());
                LogService service = (LogService) constructor.newInstance(mqConfig);
                service.setServiceName(serviceName);
                logServices.add(service);
            }
        }
    }

    public void print(ServiceConfig config) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, InterruptedException {
        this.config = config;
        init();
        for (LogService logService : logServices) {
            new PringThread(logService).start();
        }
        while(ServiceConfig.serverRunSts) {
            Thread.sleep(1000);
        }
    }

    public MqConfig getMqConfig(Class clazz, String serviceName) {
        if(clazz == RedisLogService.class) {
            return getRedisConfig(serviceName);
        }
        return null;
    }

    public RedisConfig getRedisConfig(String serviceName) {
        String key = null;
        String value = null;
        RedisConfig config = new RedisConfig(serviceName);
        try {
            PropertyDescriptor pd = null;
            Method method = null;
            Class<?> type = null;
            for (Map.Entry<Object, Object> entry : this.config.getProperties().entrySet()) {
                key = entry.getKey().toString();
                if(!key.startsWith(serviceName + ".redis.")) {
                    continue;
                }
                key = key.substring(key.lastIndexOf(".") + 1);
                value = entry.getValue() == null ? null : entry.getValue().toString().trim();
                pd = new PropertyDescriptor(key, RedisConfig.class);
                method = pd.getWriteMethod();
                type = method.getParameterTypes()[0];
                method.invoke(config, type(type, value));
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
        return config;
    }

    private Object type(Class t, String value) {
        if(value == null) {
            return null;
        }
        if(t == String.class) {
            return value;
        }
        if(t == Integer.class || "int".equals(t.toString())) {
            return Integer.parseInt(value);
        }
        return null;
    }

}
